Canigó - Servei de SFTP 2.3.x
SERVEI DE SFTP
IntroduccióPropòsitEl servei de SFTP de Canigó permet enviar i rebre arxius entre el servidor on s'executa l'aplicació a altres servidors de forma segura mitjançant l'intercanvi de claus. El servei està basat en les llibreries JSCH i Commons-VFS, la primera es tracta d'un projecte open source que permet la connexió via SSH a qualsevol màquina. La segona llibrería és un projecte també open_source de la Apache Foundation que permet treballar amb més facilitat amb la JSCH, donant eines per crear connexions SFTP (entre d'altres) contra un servidor. Context i Escenaris d'ÚsEl servei de SFTP es troba dins dels serveis d'integració de Canigó. El seu ús és necessari en cas de voler intercanviar fitxers entre servidors utilitzant el protocol SFTP, és a dir, protocol FTP de forma segura. Versions i DependènciesLes dependències descrites a la següent url son requerides per tal de compilar i fer funcionar el projecte: A qui va dirigitAquest document va dirigit als següents perfils:
Documents i Fonts de Referència
GlossariSFTP Download Upload Socket Descripció DetalladaArquitectura i ComponentsCanigó ofereix una arquitectura d'ús del protocol SFTP totalment deslligada de qualsevol implementació. Els components podem classificar-los en:
JavaDoc: http://canigo.ctti.gencat.net/confluence/canigodocs/site/canigo2_3/canigo-services-sftp/apidocs/index.html Instal.lació i ConfiguracióInstal.lacióLa instal.lació del servei requereix de la utilització de la llibreria 'canigo-services-sftp' i les dependències indicades a l'apartat 'Introducció - Versions i Dependències'. Per la instal.lació dels components Commons VFS i JSCH, no es requereix res a part dels JAR indicats en les dependències "Commons VFS" i "JSCH". ConfiguracióLa configuració del Servei de SFTP implica:
La definició del servei requereix configurar un bean amb un identificador (es recomana usar 'sftpService') i els següents atributs: Atributs:
També es poden configurar les següents propietats:
Exemple:
... <!- SFTP service -> <bean id="sftpService" class="net.gencat.ctti.canigo.services.sftp.impl.SftpServiceImpl" init-method="init"> <property name="logService"> <ref bean="loggingService" /> </property> <property name="ftpUrl" value="192.168.1.100"/> <property name="ftpPort" value="22"/> <property name="ftpUsername" value="username"/> <property name="ftpPassword" value="password"/> <property name="knownHosts" value="C:/ssh/known_hosts"/> <property name="strictHostKeyChecking" value="yes"/> </bean> ... <bean id="loggingService" class="net.gencat.ctti.canigo.services.logging.log4j.Log4JServiceImpl" init-method="init"> ... </bean> ... Exemple identificació fitxer de claus privades: ... <!- SFTP service -> <bean id="sftpService" class="net.gencat.ctti.canigo.services.sftp.impl.SftpServiceImpl" init-method="init"> <property name="logService"> <ref bean="loggingService" /> </property> <property name="ftpUrl" value="192.168.1.100"/> <property name="ftpPort" value="22"/> <property name="ftpUsername" value="username"/> <property name="identityPath" value="c:/ssh/privateKeyRSA.cfg"/> <property name="knownHosts" value="C:/ssh/known_hosts"/> <property name="strictHostKeyChecking" value="yes"/> </bean> ... <bean id="loggingService" class="net.gencat.ctti.canigo.services.logging.log4j.Log4JServiceImpl" init-method="init"> ... </bean> ... Utilització del ServeiRealitzar connexióTal i com s'ha comentat a l'apartat 'Arquitectura i Components' les classes principals per realitzar transferències de fitxers es troben al package 'net.gencat.ctti.canigo.services.sftp'. Per realitzar una connexió segura només cal inicialitzar el bean tal i com s'ha indicat a l'apartat 'Configuració'. if (this.sftpService!= null ) { sftpService.login(); } En canvi, si no hem indicat a través de la configuració l'usuari i la contrasenya per realitzar la connexió, es farà la següent crida: if (this.sftpService!= null ) { sftpService.login(usuari,contrasenya); } A més a més, l'API del servei permet fer la connexió a un servidor de forma dinàmica, és a dir, es pot indicar l'adreça i port del servidor al que ens volem connectar en temps d'execució, per fer-ho el servei ofereix un tercer mètode de login: if (this.sftpService!= null ) { sftpService.login(usuari,contrasenya,ftpUrl,ftpPort); } Realitzarem doncs els següents passos:
El mètode retorna un valor booleà (TRUE/FALSE) indicant si la connexió s'ha realitzat correctament. NOTA: Per realitzar una connexió al servidor a través d'un proxy cal informar els següents camps:
Realitzar desconnexió del servidor SFTPPer realitzar la desconnexió del servidor FTP seguirem un patró com el mostrat en el següent exemple:
if (this.sftpService!= null ) { if (sftpService.isLogged()) { sftpService.logout(); } } Realitzarem doncs els següents passos:
Realitzar download d'un fitxerPer realitzar un download d'un fitxer seguirem un patró com el mostrat en el següent exemple:
if (this.sftpService!= null ) { sftpService.login(); if (sftpService.isLogged()) { sftpService.downloadFile(fileName, localPath, remotePath); sftpService.logout(); } } Realitzarem doncs els següents passos:
Es crida el mètode downloadFile() que amb els següents paràmetres:
I retorna:
Realitzar upload d'un fitxerPer realitzar un upload d'un fitxer seguirem un patró com el mostrat en el següent exemple:
if (this.sftpService!= null ) { sftpService.login(); if (sftpService.isLogged()) { sftpService.uploadFile(fileName, localPath, remotePath); sftpService.logout(); } } Realitzarem doncs els següents passos:
Es crida el mètode uploadFile() que amb els següents paràmetres:
Obtenir la llista de noms dels fitxers del servidor remotPer obtenir la llista de fitxers en una carpeta d'un servidor remot seguirem un patró com el mostrat en el següent exemple:
if (this.sftpService!= null ) { sftpService.login(); if (sftpService.isLogged()) { FileObject[] listFiles = sftpService.listFiles(remotePath); sftpService.logout(); } } Realitzarem doncs els següents passos:
Es crida el mètode listFiles() que amb els següents paràmetres:
El mètode retorna un array de FileObject, interfícies de la llibrería Commons VFS que ens donen una sèrie de mètodes per a treballar amb els fitxers remots. Crear un fitxer al servidor remotPer crear un fitxer al servidor remot seguirem un patró com el mostrat en el següent exemple:
if (this.sftpService!= null ) { sftpService.login(); if (sftpService.isLogged()) { createFile(fileName, remotePath); sftpService.logout(); } } Realitzarem doncs els següents passos:
Es crida el mètode createFile() que amb els següents paràmetres:
El mètode retorna un boolean TRUE o FALSE segons s'ha realitzat correcta o incorrectament el procés. Crear un directori al servidor remotPer crear un directori al servidor remot seguirem un patró com el mostrat en el següent exemple:
if (this.sftpService!= null ) { sftpService.login(); if (sftpService.isLogged()) { createFolder(folderName, remotePath); sftpService.logout(); } } Realitzarem doncs els següents passos:
Es crida el mètode createFolder() que amb els següents paràmetres:
El mètode retorna un boolean TRUE o FALSE segons s'ha realitzat correcta o incorrectament el procés. Esborrar un fitxer al servidor remotPer esborrar un fitxer al servidor remot seguirem un patró com el mostrat en el següent exemple:
if (this.sftpService!= null ) { sftpService.login(); if (sftpService.isLogged()) { deleteFile(fileName, remotePath); sftpService.logout(); } } Realitzarem doncs els següents passos:
Es crida el mètode deleteFile() que amb els següents paràmetres:
El mètode retorna un boolean TRUE o FALSE segons s'ha realitzat correcta o incorrectament el procés. ExemplesTests UnitarisUn exemple d'utilització del servei de SFTP són els tests unitaris, a on s'obté el bean del servei a partir del fitxer de definició (applicationContext.xml). S'ha de tenir en compte que s'ha de disposar d'accés a un servidor remot mitjançant el protocol SFTP per poder realitzar els tests. package net.gencat.ctti.canigo.services.sftp.test; ... La utilització del servei es independent de la configuració del mateix. Així, un possible fitxer de configuració del servei seria:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="sftpService" class="net.gencat.ctti.canigo.services.sftp.impl.SftpServiceImpl" init-method="init"> <property name="logService"> <ref bean="loggingService" /> </property> <property name="ftpUsername" value="user"/> <property name="ftpPassword" value="pass"/> <property name="ftpUrl" value="192.168.131.75"/> <property name="ftpPort" value="22"/> <property name="knownHosts" value="C:/ssh/known_hosts"/> <property name="strictHostKeyChecking" value="yes"/> </bean> <!-- LOGGING service --> <bean id="loggingService" class="net.gencat.ctti.canigo.services.logging.log4j.Log4JServiceImpl"> <property name="configurator"> <ref local="loggingConfigurator"/> </property> </bean> <!-- configurator bean --> <bean id="loggingConfigurator" class="net.gencat.ctti.canigo.services.logging.log4j.xml.HostDOMConfigurator" init-method="init"> <property name="configFileName"> <value>classpath:log4j-test.xml</value> </property> </bean> </beans> ... public void testLogin() throws Exception { try { SftpService sftpService = getSftpService(); assertTrue(sftpService.login()); if (sftpService.isLogged()) { sftpService.logout(); } } catch (SftpServiceException e) { log.error(e.getCause()); } } public void testLoginFailed() throws Exception { try { SftpService sftpService = getSftpService(); assertFalse(sftpService.login("username", "incorrectPassword")); if (sftpService.isLogged()) { sftpService.logout(); } } catch (SftpServiceException e) { log.error(e.getCause()); } } public void testUploadFile() throws Exception { String file = "file_"+System.currentTimeMillis()+".txt"; try { SftpService sftpService = getSftpService(); sftpService.login(); sftpService.uploadFile(file, localPath, remotePath); assertTrue(sftpService.existsFile(remotePath, file)); if(sftpService.isLogged()) { sftpService.logout(); } } catch (SftpServiceException e) { log.error(e.getCause()); } } public void testDownloadFile() throws Exception { try { SftpService sftpService = getSftpService(); sftpService.login(); if(!sftpService.existsFile(remotePath, fileName)) { sftpService.uploadFile(fileName, localPath, remotePath); } sftpService.downloadFile(fileName, localPath, remotePath); if(sftpService.isLogged()) { sftpService.logout(); } File file = new File(localPath+"/"+fileName); assertTrue(file.exists()); } catch (SftpServiceException e) { log.error(e.getCause()); } } public void testCreateFolder() throws Exception { String folder = "folder_"+System.currentTimeMillis(); try { SftpService sftpService = getSftpService(); sftpService.login(); sftpService.createFolder(remotePath,folder); assertTrue(sftpService.existsFolder(remotePath,folder)); if(sftpService.isLogged()) { sftpService.logout(); } } catch (SftpServiceException e) { log.error(e.getCause()); } } public void testDeleteFile() throws Exception { String file = "file_"+System.currentTimeMillis()+".txt"; try { SftpService sftpService = getSftpService(); sftpService.login(); sftpService.createFile(remotePath,file); assertTrue(sftpService.deleteFile(remotePath,file)); if(sftpService.isLogged()) { sftpService.logout(); } } catch (SftpServiceException e) { log.error(e.getCause()); } } public void testListFiles() throws Exception { try { SftpService sftpService = getSftpService(); sftpService.login(); assertNotNull(sftpService.listFiles(remotePath)); if(sftpService.isLogged()) { sftpService.logout(); } } catch (SftpServiceException e) { log.error(e.getCause()); } } private SftpService getSftpService() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml"); SftpService sftpService = (SftpService)beanFactory.getBean("sftpService"); logService = sftpService.getLogService(); log = logService.getLog(SftpServiceTest.class); assertNotNull(sftpService); return sftpService; } ... |